﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;

namespace Lib.Data;
/// <summary>
/// 程序集加载器
/// </summary>
internal class AssemblyLoader {
    /// <summary>
    /// 静态构造函数
    /// </summary>
    static AssemblyLoader() {
        Ins = []; Assemblys = [];
    }
    /// <summary>
    /// 类的类型列表（集合）
    /// </summary>
    public static Dictionary<string, Type> Ins { get; internal set; }
    /// <summary>
    /// 程序集信息列表（集合）
    /// </summary>
    public static Dictionary<string, Assembly> Assemblys { get; internal set; }
    /// <summary>
    /// 动态加载程序集并返回指定类的类型
    /// </summary>
    public static Type LoadAssemblyFile(string Path, string ClassName) {
        if (Ins.TryGetValue(ClassName, out Type Value)) {
            return Value;
        }
        Path = Path.Replace(@"\", "/");
        if (Path.Contains(":/") || Path.StartsWith('/')) {

        } else {
            Path = System.IO.Path.Combine(Directory.GetCurrentDirectory(), Path).Replace(@"\", "/");
        }
        if (System.IO.File.Exists(Path)) {
            var File = System.IO.Path.GetFileName(Path);
            try {
                AssemblyLoadContext Context;
                Assembly Assembly;
                if (Assemblys.TryGetValue(Path, out Assembly _Assembly)) {
                    Assembly = _Assembly;
                } else {
                    Context = new AssemblyLoadContext(Path);
                    Assembly = Context.LoadFromAssemblyPath(Path);
                    if (Assembly == null) {
                        return null;
                    }
                    Assemblys.Add(Path, Assembly);
                    Context.Resolving += (Context, AssemblyName) => {
                        var Path = System.IO.Path.Combine(Directory.GetParent(Context.Name).FullName, $"{AssemblyName.Name}.DLL").Replace(@"\", "/");
                        if (System.IO.File.Exists(Path)) {
                            try {
                                var Assembly = Context.LoadFromAssemblyPath(Path);
                                if (Assembly == null) {
                                    return null;
                                }
                                Console.WriteLine($"\n加载依赖项 {Path} 成功");
                                return Assembly;
                            } catch (Exception ex) {
                                Console.WriteLine($"\n加载依赖项 {Path} 失败");
                                Console.WriteLine($"\n依赖项信息 {ex.Message}");
                            }
                        } else {
                            Console.WriteLine($"\n依赖项文件不存在 {Path}");
                        }
                        return null;
                    };
                }
                var Type = Assembly.GetType(ClassName);
                if (Type == null) {
                    return null;
                }
                Ins.Add(ClassName, Type);
                Console.WriteLine($"\n程序集路径 {Path}");
                Console.WriteLine($"\n加载程序集 {File},{ClassName} 成功");
                return Type;
            } catch (Exception ex) {
                Console.WriteLine($"\n程序集路径 {Path}");
                Console.WriteLine($"\n加载程序集 {File} 失败");
                Console.WriteLine($"\n程序集信息 {ex.Message}");
            }
        } else {
            Console.WriteLine($"\n程序集文件不存在 {Path}");
        }
        return null;
    }

}
